package com.newtouch.serviceconsumerwebfluxresilience4j;

import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerExchangeFilterFunction;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

@SpringBootApplication
@EnableDiscoveryClient
@RestController
@Configuration
public class ServiceConsumerWebfluxResilience4jApplication {

    @Autowired
    private ReactorLoadBalancerExchangeFilterFunction lbFunction;

    @Bean
    public WebClient webClient() {
        return WebClient.builder().filter(lbFunction).build();
    }

    public static void main(String[] args) {
        SpringApplication.run(ServiceConsumerWebfluxResilience4jApplication.class, args);
    }

    @GetMapping("/")
    @Bulkhead(name="sayHello", fallbackMethod = "helloFallback")
    @RateLimiter(name="sayHello", fallbackMethod = "helloFallback")
    @Retry(name="sayHello", fallbackMethod = "helloFallback")
    @CircuitBreaker(name="sayHello", fallbackMethod = "helloFallback")
    public Mono<String> sayHello() {
        return webClient().get().uri("http://service-hello-webflux/").retrieve().bodyToMono(String.class);
    }

    public Mono<String> helloFallback(Throwable throwable) {
        return Mono.just(String.format("fallback broken! the reason is %s", throwable.getLocalizedMessage()));
    }

}
